<template>
  <div class="chat-container">
    <div class="toolbar">
      <t-button
        variant="outline"
        icon="download"
        @click="openDownloadDialog"
        class="toolbar-button download-button"
      >
        下载记录
      </t-button>
      <t-button
        variant="outline"
        icon="share"
        @click="shareConversation"
        class="toolbar-button share-button"
      >
        分享记录
      </t-button>
      <t-button
        variant="outline"
        icon="theme"
        @click="$toggleTheme()"
        shape="round"
        class="toolbar-button theme-button"
      >
        切换风格
      </t-button>
    </div>

    <t-chat
      ref="chatRef"
      layout="single"
      class="chat-window"
      :clear-history="chatList.length > 0 && !isStreamLoad"
      @clear="clearConfirm"
    >
      <template v-for="(item, index) in chatList" :key="index">
        <t-chat-item
          :avatar="item.avatar"
          :name="item.name"
          :role="item.role"
          :datetime="item.datetime"
          :text-loading="index === 0 && loading"
        >
          <template #content>
            <div
              :class="['chat-bubble', item.role === 'user' ? 'user-bubble' : 'assistant-bubble']"
              v-html="item.content"
            ></div>
          </template>
          <template v-if="!isStreamLoad" #actions>
            <t-chat-action
              :is-good="isGood[index]"
              :is-bad="isBad[index]"
              :content="item.content"
              @operation="(type, { e }) => handleOperation(type, { e, index })"
              :class="{ 
                'active-good': isGood[index],
                'active-bad': isBad[index]
              }"
            />
          </template>
        </t-chat-item>
      </template>

      <template #footer>
        <div class="input-area">
          <t-chat-input 
            :stop-disabled="isStreamLoad" 
            @send="inputEnter" 
            @stop="onStop" 
            placeholder="请输入您的问题..."
            class="chat-input"
          />
          <t-button
            v-if="isStreamLoad"
            @click="onStop"
            type="danger"
            icon="close"
            circle
            class="stop-button"
          />
        </div>
      </template>
    </t-chat>

    <t-dialog
      v-model:visible="showFeedbackForm"
      title="反馈信息"
      :mask-closable="false"
      :show-close="false"
      width="500px"
      class="feedback-dialog"
    >
      <div>
        <p>请输入您的反馈（可选）：</p>
        <t-textarea 
          v-model="feedbackContent" 
          placeholder="请输入您的反馈（可选）" 
          :rows="4" 
          class="feedback-textarea" 
        />
      </div>
      <template #footer>
        <t-button @click="closeFeedbackForm" class="cancel-feedback-button">取消</t-button>
        <t-button type="primary" @click="submitFeedback" class="submit-feedback-button">提交</t-button>
      </template>
    </t-dialog>
、
    <t-dialog
      v-model:visible="showShareDialog"
      title="分享记录"
      :mask-closable="false"
      :show-close="false"
      width="500px"
      class="share-dialog"
    >
      <div class="share-content">
        <t-textarea
          v-model="shareText"
          placeholder="写下您想分享的内容..."
          class="share-text-input"
        />
        <t-upload
          class="share-image-upload"
          :action="uploadAction"
          :show-file-list="false"
          :limit="1"
          :auto-upload="false"
          :on-change="handleImageChange"
        >
          <t-button variant="outline" icon="upload">上传图片</t-button>
        </t-upload>
        <div v-if="shareImage" class="image-preview">
          <img :src="shareImage" alt="图片预览" />
          <t-button variant="text" icon="close" @click="removeImage" class="remove-image-button">移除</t-button>
        </div>
      </div>
      <template #footer>
        <t-button type="primary" @click="submitShare" class="submit-share-button">分享</t-button>
      </template>
    </t-dialog>

    <!-- 下载对话框 -->
    <t-dialog
      v-model:visible="showDownloadDialog"
      title="下载对话记录"
      :mask-closable="false"
      :show-close="false"
      width="400px"
      class="download-dialog"
    >
      <div class="download-content">
        <p>是否确认下载当前对话记录？</p>
        <p>文件格式：<strong>TXT</strong></p>
      </div>
      <template #footer>
        <t-button @click="closeDownloadDialog" class="cancel-download-button">取消</t-button>
        <t-button type="primary" @click="confirmDownload" class="confirm-download-button">确认下载</t-button>
      </template>
    </t-dialog>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { MessagePlugin } from 'tdesign-vue-next';
import { saveAs } from 'file-saver'; 
import { Upload } from 'tdesign-vue-next';

// 反馈表单相关的状态
const showFeedbackForm = ref(false);
const feedbackType = ref(null); // 'good' 或 'bad'
const currentFeedbackIndex = ref(null);
const feedbackContent = ref('');

// 分享对话框相关的状态
const showShareDialog = ref(false);
const shareText = ref('');
const shareImage = ref(null);
const uploadAction = '/your-upload-endpoint'; // 替换为实际的上传接口

// 下载对话框相关的状态
const showDownloadDialog = ref(false);

/**
 * 打开下载对话框
 */
const openDownloadDialog = () => {
  showDownloadDialog.value = true;
};

/**
 * 关闭下载对话框
 */
const closeDownloadDialog = () => {
  showDownloadDialog.value = false;
};

/**
 * 确认下载操作
 */
const confirmDownload = () => {
  downloadConversation();
  showDownloadDialog.value = false;
};

/**
 * 滚动到底部
 */
const chatRef = ref(null);
const backBottom = () => {
  chatRef.value.scrollToBottom({
    behavior: 'smooth',
  });
};

// 初始化聊天记录，仅保留初始机器人问候
const chatList = ref([
  {
    avatar: 'https://i.pravatar.cc/150?img=12',
    name: '美食博主',
    datetime: '今天16:38',
    content: '我是美食的狂热者，典型的大吃货，你有什么想问我的吗。',
    role: 'assistant',
  },
]);

// 初始化 isGood 和 isBad 数组
const isGood = ref([]);
const isBad = ref([]);

const initializeFeedbackStates = () => {
  isGood.value = chatList.value.map(() => false);
  isBad.value = chatList.value.map(() => false);
};

// 调用初始化方法
initializeFeedbackStates();

const fetchCancel = ref(null);
const loading = ref(false);
const isStreamLoad = ref(false);

/**
 * Clears the confirmation by resetting the chat list to an empty array.
 */
const clearConfirm = function () {
  chatList.value = [];
  initializeFeedbackStates();
};

/**
 * Handles the stop event for a fetch operation.
 */
const onStop = function () {
  if (fetchCancel.value) {
    fetchCancel.value.abort();
    loading.value = false;
    isStreamLoad.value = false;
  }
};

/**
 * Handles different types of operations based on the provided type and options.
 * 增加反馈表单的触发逻辑
 */
const handleOperation = function (type, options) {
  const { index } = options;
  if (type === 'good') {
    isGood.value[index] = !isGood.value[index];
    if (isGood.value[index]) {
      isBad.value[index] = false;
      // 打开反馈表单
      feedbackType.value = 'good';
      currentFeedbackIndex.value = index;
      showFeedbackForm.value = true;
    }
  } else if (type === 'bad') {
    isBad.value[index] = !isBad.value[index];
    if (isBad.value[index]) {
      isGood.value[index] = false;
      // 打开反馈表单
      feedbackType.value = 'bad';
      currentFeedbackIndex.value = index;
      showFeedbackForm.value = true;
    }
  } else if (type === 'replay') {
    const userQuery = chatList.value[index + 1].content;
    inputEnter(userQuery);
  }
};

/**
 * 提交反馈表单
 */
const submitFeedback = () => {
  if (currentFeedbackIndex.value === null) {
    MessagePlugin.error('未找到对应的消息！');
    return;
  }

  // 显示固定成功消息
  MessagePlugin.info('提交成功，我们将根据你的反馈对后面的内容进行调整！');

  // 关闭反馈表单
  showFeedbackForm.value = false;
};

/**
 * 关闭反馈表单
 */
const closeFeedbackForm = () => {
  showFeedbackForm.value = false;
};

/**
 * 打开分享对话框
 */
const shareConversation = () => {
  showShareDialog.value = true;
};

/**
 * 处理图像上传
 */
const handleImageChange = (info) => {
  if (info.file.status === 'done') {
    // 假设上传成功，获取图片URL
    shareImage.value = info.file.response.url;
    MessagePlugin.success('图片上传成功！');
  } else if (info.file.status === 'error') {
    MessagePlugin.error('图片上传失败，请重试。');
  }
};

/**
 * 移除已上传的图片
 */
const removeImage = () => {
  shareImage.value = null;
};

/**
 * 提交分享内容
 */
const submitShare = () => {
  if (!shareText.value && !shareImage.value) {
    MessagePlugin.error('请输入文本或上传图片后再分享。');
    return;
  }

  // 实现分享逻辑，例如调用API或使用Web Share API
  // 这里假设分享成功
  MessagePlugin.success('分享成功！');

  // 清空分享内容
  shareText.value = '';
  shareImage.value = null;

  // 关闭分享对话框
  showShareDialog.value = false;
};

/**
 * Handles the asynchronous processing of user input data.
 * Sends the input message to a server via Server-Sent Events (SSE)
 * and updates the chat list with the server's response.
 *
 * @param {string} inputValue - The message content entered by the user.
 */
const handleData = async (inputValue) => {
  loading.value = true;
  isStreamLoad.value = true;
  const lastItem = chatList.value[0];
  const messages = [{
    role: 'user',
    content: inputValue,
  }];
  fetchSSE(messages, {
    success(result) {
      loading.value = false;
      const { data } = result;
      lastItem.content += data?.delta?.content;
    },
    complete(isOk, msg) {
      if (!isOk || !lastItem.content) {
        lastItem.role = 'error';
        lastItem.content = msg;
      }
      isStreamLoad.value = false;
      loading.value = false;
    },
    cancel(cancel) {
      fetchCancel.value = cancel;
    },
  });
};

/**
 * Handles the input when the enter key is pressed.
 * If the stream is loading, it does nothing.
 * If the input value is empty, it also does nothing.
 * Otherwise, it creates a user message object and prepends it to the chat list.
 * It then creates an assistant placeholder message object and prepends it to the chat list.
 * Finally, it calls the handleData function with the input value.
 * @param {string} inputValue - The value of the input field when enter is pressed.
 */
const inputEnter = function (inputValue) {
  if (isStreamLoad.value) {
    return;
  }
  if (!inputValue) return;
  const params = {
    avatar: 'https://i.pravatar.cc/150?img=8',
    name: '自己',
    datetime: new Date().toLocaleString(),
    content: inputValue,
    role: 'user',
  };
  chatList.value.unshift(params);
  // 空消息占位
  const params2 = {
    avatar: 'https://i.pravatar.cc/150?img=12',
    name: '美食博主',
    datetime: new Date().toLocaleString(),
    content: '',
    role: 'assistant',
  };
  chatList.value.unshift(params2);
  isGood.value.unshift(false);
  isBad.value.unshift(false);
  handleData(inputValue);
};

const fetchSSE = async (messages, options) => {
  const { success, fail, complete, cancel } = options;
  const controller = new AbortController();
  const { signal } = controller;
  cancel?.(controller);
  const apiKey = 'sk-6R0hq8U7v3bSbT1u41Lp6kPRwAgf9wnW73WgvSC7WUI73eRO';
  const responsePromise = fetch('/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer${apiKey ? ` ${apiKey}` : ''}`,
    },
    body: JSON.stringify({
      messages, 
      model: 'hunyuan-pro', 
      stream: true,
    }),
    signal,
  }).catch((e) => {
    const msg = e.toString() || '流式接口异常';
    complete?.(false, msg);
    return Promise.reject(e); 
  });

  responsePromise
    .then((response) => {
      if (!response?.ok) {
        complete?.(false, response.statusText);
        fail?.();
        throw new Error('Request failed'); 
      }
      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      if (!reader) throw new Error('No reader available');

      const bufferArr = [];
      let dataText = ''; 
      const event = { type: null, data: null };

      async function processText({ done, value }) {
        if (done) {
          complete?.(true);
          return Promise.resolve();
        }
        const chunk = decoder.decode(value);
        const buffers = chunk.toString().split(/\r?\n/);
        bufferArr.push(...buffers);
        let i = 0;
        while (i < bufferArr.length) {
          const line = bufferArr[i];
          if (line) {
            dataText += line;
            const response = line.slice(6);
            if (response === '[DONE]') {
              event.type = 'finish';
              dataText = '';
            } else {
              try {
                const choices = JSON.parse(response.trim())?.choices?.[0];
                if (choices.finish_reason === 'stop') {
                  event.type = 'finish';
                  dataText = '';
                } else {
                  event.type = 'delta';
                  event.data = choices;
                }
              } catch (error) {
                console.error('解析错误:', error);
              }
            }
          }
          if (event.type && event.data) {
            const jsonData = { ...event };
            success(jsonData);
            event.type = null;
            event.data = null;
          }
          bufferArr.splice(i, 1);
        }
        return reader.read().then(processText);
      }

      return reader.read().then(processText);
    })
    .catch(() => {
      fail?.();
    });
};

const downloadConversation = () => {
  const conversation = chatList.value
    .map((msg) => {
      const time = new Date(msg.datetime).toLocaleString();
      const content = msg.content.replace(/<[^>]+>/g, '');
      return `[${time}] ${msg.name} (${msg.role}): ${content}`;
    })
    .reverse() 
    .join('\n\n');

  const blob = new Blob([conversation], { type: 'text/plain;charset=utf-8' });
  saveAs(blob, 'conversation.txt');
};
</script>